#include "f_lcd_gui.h"
#include "spi_dev.h"

#include "string.h"
#include "math.h"
#include "mymath.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "font.h"
#include "hw_lcd.h"
#define LCD_HIGH 320 //Y
#define LCD_WIDTH 240 //X

#define RGB_RED_OF_COLOR16(x) ((x>>11)<<3)
#define RGB_GREEN_OF_COLOR16(x) (((x&0x730)>>5)<<2)
#define RGB_BLUE_OF_COLOR16(x) ((x&0x1f)<<3)
#define RGB_COLOR_T_TO_COLOR16(x) (((x.r>>3)<<11)+((x.g>>2)<<5)+(x.b>>3))

//有缺陷用静态这么大变量做,可以换成缓存申请注册
static uint8_t LCD_GRAM [LCD_HIGH][LCD_WIDTH][2] = {0};
 
 /*内存申请注册函数*/
static uint8_t * buf = NULL;
void f_gui_init(void)
{
    buf = malloc(LCD_HIGH*LCD_WIDTH*2);
}

void f_gui_delete(void)
{
    free(buf);
}

//0-169 //0 -319
void f_lcd_draw_point(uint16_t x,uint16_t y ,uint16_t color)//点
{   
    if ((y>(LCD_HIGH-1))|| (x>(LCD_WIDTH-1)))
	{
		return;
	}
    *(buf+y*LCD_WIDTH+x) = (color >> 8);
    *(buf+y*LCD_WIDTH+x+1) = color & 0x00FF;
}

void f_lcd_clear_ram(void)
{
    memset(buf,0,LCD_HIGH*LCD_WIDTH*2);
}

void f_lcd_refresh(void)
{
    lv_refresh(0,0,LCD_WIDTH,LCD_HIGH,buf);
}

/*全屏颜色刷新*/
void f_lcd_color_fill(uint16_t color)
{
	uint8_t data[2] = {(color >> 8),color & 0xFF};
    for (uint16_t i = 0; i < LCD_HIGH; i++)
    {
        for (uint16_t j = 0; j < LCD_WIDTH; j++)
        {
            *(buf+i*LCD_WIDTH+j) = data[0];
            *(buf+i*LCD_WIDTH+j+1) = color & 0x00FF;
            // LCD_GRAM [i][j][0] = data[0];
            // LCD_GRAM [i][j][1] = data[1];
        }
    }
}

/*------------------------------------------*/
void gui_clear_ram(void) //清空数组为黑屏
{
    memset(LCD_GRAM,0,LCD_HIGH*LCD_WIDTH*2);
}

void Gui_Refresh(void)
{
    lv_refresh(0,0,LCD_WIDTH,LCD_HIGH,LCD_GRAM);
}

void gui_center_diffuse_refresh(uint16_t style)
{
    switch (style)
    {
    case 0://从上到下刷新
        for (uint16_t i = 0; i < LCD_HIGH; i++)
        {
            Gui_refresh_any_area(0,i,LCD_WIDTH,1);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        break;
    case 1://中间起始上下刷新
        for (uint16_t i = 0; i < LCD_HIGH/2; i++)
        {
            Gui_refresh_any_area(0,LCD_HIGH/2+i,LCD_WIDTH,1);
            Gui_refresh_any_area(0,LCD_HIGH/2-i-1,LCD_WIDTH,1);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        break;
    case 2://斜角缩放刷新
        Gui_refresh_any_area(0,0,20,20);
        for (uint16_t i = 20; i < LCD_HIGH; i++)
        {
            Gui_refresh_any_area(0,i,i/2+1,1);
            Gui_refresh_any_area(i/2,0,1,i+1);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        for (uint16_t i = LCD_HIGH/2; i < LCD_WIDTH; i++)//当长宽不是2:1的时候剩下的刷新
        {
            Gui_refresh_any_area(i,0,1,LCD_HIGH);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        break;
    case 3://两边起始向中间刷新
        for (uint16_t i = 0; i < LCD_HIGH/2; i++)
        {
            Gui_refresh_any_area(0,i,LCD_WIDTH,1);
            Gui_refresh_any_area(0,LCD_HIGH-i-1,LCD_WIDTH,1);
            vTaskDelay(pdMS_TO_TICKS(5));
        }        
        break;
    case 4://斜角缩放刷新
        for (uint16_t i = LCD_WIDTH; i > LCD_HIGH/2-1; i--)//当长宽不是2:1的时候剩下的刷新
        {
            Gui_refresh_any_area(i,0,1,LCD_HIGH);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        for (uint16_t i = LCD_HIGH; i > 20; i--)
        {
            Gui_refresh_any_area(0,i,i/2+1,1);
            Gui_refresh_any_area(i/2,0,1,i+1);
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        Gui_refresh_any_area(0,0,20,21);
        break;
    }
}

//0-169 //0 -319
void lcd_draw_point(uint16_t x,uint16_t y ,uint16_t color)//点
{   
    if ((y>(LCD_HIGH-1))|| (x>(LCD_WIDTH-1)))
	{
		return;
	}
    LCD_GRAM[y][x][0]= (color >> 8);
    LCD_GRAM[y][x][1]= color & 0x00FF;
}

void lcd_animation_move(uint16_t x ,uint16_t y ,uint16_t length ,uint16_t high,void *p)
{
    uint8_t y_end = y+high-1; //最下面的y轴  //Y
    uint8_t x_offset = length*2; //输入图形的一行
    for(uint8_t i = 0 ; i<high; i++ )
    {
        for(uint8_t j = 0; j < i+1 ; j++)
        {
            memcpy(&LCD_GRAM[y_end-i+j][x][0], (uint8_t *)p +j*x_offset,x_offset); //数组每次的赋值 j行
        }
    }
}

//刷新缓存局部位置
/*将缓存数组的数据，整理出来一个连续的块，一起发送.
每一次for循环，复制一条x轴
数据不能太短与16个字节，spi控制器最小发16个字节
*/
void Gui_refresh_any_area(uint16_t x ,uint16_t y,uint16_t length,uint16_t high)
{
    if (x + length>LCD_WIDTH|| y + high>LCD_HIGH)
    {
    return;
    }
    uint8_t *ptr = (uint8_t*)malloc(length * high * 2);  
    if (ptr == NULL) {
        return;  
    }  
    for (uint16_t i = y; i < y + high; i++) {  
        memcpy(ptr + (i - y)*length*2,&LCD_GRAM[i][x][0], length * 2);  
    } 
    lv_refresh(x, y, x + length, y + high, ptr);  
    free(ptr);  
}

// printf("free_heap_size = %ld\n", esp_get_free_heap_size());

//刷新图片函数 ,局部刷新图片，直接将图片数据拷贝进对应缓存的位置
void Gui_draw_cache_picture(uint16_t x,uint16_t y,uint16_t length,uint16_t high,const void *p)
{
    if (length>LCD_WIDTH ||high >LCD_HIGH)
    {
        return;
    }
    
    uint8_t * temp = (uint8_t *)p;
    for (uint16_t i = y; i < high; i++)
    {
        temp = (uint8_t *)p+(length*2*i);
        memcpy(&LCD_GRAM[i][x][0],temp,(length*2));
    }
}

/*
r:直径
fc：颜色
*/
void Gui_Circle_Bresenham(uint16_t X,uint16_t Y,uint16_t R,uint16_t fc) //画圆算法
{//Bresenham算法 
    unsigned short  a,b; 
    int c; 
    a=0; 
    b=R; 
    c=3-2*R; 
    while (a<b) 
    { 
        lcd_draw_point(X+a,Y+b,fc);     //        7 
        lcd_draw_point(X-a,Y+b,fc);     //        6 
        lcd_draw_point(X+a,Y-b,fc);     //        2 
        lcd_draw_point(X-a,Y-b,fc);     //        3 
        lcd_draw_point(X+b,Y+a,fc);     //        8 
        lcd_draw_point(X-b,Y+a,fc);     //        5 
        lcd_draw_point(X+b,Y-a,fc);     //        1 
        lcd_draw_point(X-b,Y-a,fc);     //        4 
        if(c<0) c=c+4*a+6; 
        else 
        { 
            c=c+4*(a-b)+10; 
            b-=1; 
        } 
       a+=1; 
    } 
    if (a==b) 
    { 
        lcd_draw_point(X+a,Y+b,fc); 
        lcd_draw_point(X+a,Y+b,fc); 
        lcd_draw_point(X+a,Y-b,fc); 
        lcd_draw_point(X-a,Y-b,fc); 
        lcd_draw_point(X+b,Y+a,fc); 
        lcd_draw_point(X-b,Y+a,fc); 
        lcd_draw_point(X+b,Y-a,fc); 
        lcd_draw_point(X-b,Y-a,fc); 
    } 
} 

void Gui_Gear_Circle_Bresenham(uint16_t X,uint16_t Y,uint16_t R,uint16_t fc)//实心圆
{
    unsigned short  a,b; 
    int c; 
    a=0; 
    b=R; 
    c=3-2*R; 
    while (a<b) 
    { 
        lcd_draw_point(X+a,Y+b,fc);     //        7 
        lcd_draw_point(X-a,Y+b,fc);     //        6 
        lcd_draw_point(X+a,Y-b,fc);     //        2 
        lcd_draw_point(X-a,Y-b,fc);     //        3 
        lcd_draw_point(X+b,Y+a,fc);     //        8 
        lcd_draw_point(X-b,Y+a,fc);     //        5 
        lcd_draw_point(X+b,Y-a,fc);     //        1 
        lcd_draw_point(X-b,Y-a,fc);     //        4 
        if(c<0) c=c+4*a+6; 
        else 
        { 
            c=c+4*(a-b)+10; 
            b-=1; 
        } 
       a+=1; 
    } 
    if (a==b) 
    { 
        lcd_draw_point(X+a,Y+b,fc); 
        lcd_draw_point(X+a,Y+b,fc); 
        lcd_draw_point(X+a,Y-b,fc); 
        lcd_draw_point(X-a,Y-b,fc); 
        lcd_draw_point(X+b,Y+a,fc); 
        lcd_draw_point(X-b,Y+a,fc); 
        lcd_draw_point(X+b,Y-a,fc); 
        lcd_draw_point(X-b,Y-a,fc); 
    } 
}

//sin画圆算法
void Gui_Circle_math(uint16_t x0 ,uint16_t y0 ,uint16_t R ,uint16_t color)
{
    float Rx,Ry,angle,Rad;
    for (angle = 0; angle < 360; angle++)
    {
        Rad = angle *3.14/180;
        Rx = R*cos(Rad);
        Ry = R*sin(Rad);
        lcd_draw_point(x0+Rx,64-y0+Ry,color);
    }
}

//画线函数，使用Bresenham 画线算法
void Gui_DrawLine_Bresenham(uint16_t x0, uint16_t y0,uint16_t x1, uint16_t y1,uint16_t Color)   
{
    int dx,             // difference in x's
    dy,             // difference in y's
    dx2,            // dx,dy * 2
    dy2, 
    x_inc,          // amount in pixel space to move during drawing
    y_inc,          // amount in pixel space to move during drawing
    error,          // the discriminant i.e. error i.e. decision variable
    index;          // used for looping	

	dx = x1-x0;//计算x距离
	dy = y1-y0;//计算y距离

	if (dx>=0)
	{
		x_inc = 1;
	}
	else
	{
		x_inc = -1;
		dx    = -dx;  
	} 
	
	if (dy>=0)
	{
		y_inc = 1;
	} 
	else
	{
		y_inc = -1;
		dy    = -dy; 
	} 

	dx2 = dx << 1;
	dy2 = dy << 1;

	if (dx > dy)//x距离大于y距离，那么每个x轴上只有一个点，每个y轴上有若干个点
	{//且线的点数等于x距离，以x轴递增画点
		// initialize error term
		error = dy2 - dx; 
		// draw the line
		for (index=0; index <= dx; index++)//要画的点数不会超过x距离
		{
			//画点
			lcd_draw_point(x0,y0,Color);
			
			// test if error has overflowed
			if (error >= 0) //是否需要增加y坐标值
			{
				error-=dx2;

				// move to next line
				y0+=y_inc;//增加y坐标值
			} // end if error overflowed

			// adjust the error term
			error+=dy2;

			// move to the next pixel
			x0+=x_inc;//x坐标值每次画点后都递增1
		} // end for
	} // end if |slope| <= 1
	else//y轴大于x轴，则每个y轴上只有一个点，x轴若干个点
	{//以y轴为递增画点
		// initialize error term
		error = dx2 - dy; 

		// draw the line
		for (index=0; index <= dy; index++)
		{
			// set the pixel
			lcd_draw_point(x0,y0,Color);

			// test if error overflowed
			if (error >= 0)
			{
				error-=dy2;

				// move to next line
				x0+=x_inc;
			} // end if error overflowed

			// adjust the error term
			error+=dx2;

			// move to the next pixel
			y0+=y_inc;
		} // end for
	} // end else |slope| > 1
}

void Gui_DrawLine(uint16_t x0 ,uint16_t y0 ,uint16_t x1,uint16_t y1,uint8_t dot,uint16_t color)
{
    uint16_t lx = abs(x1-x0);
    uint16_t ly = abs(y1-y0);
    uint16_t dm,i;
    float dx,dy;
    float x,y;

    if(lx >= ly)
        dm = lx;
    else
        dm = ly;
    
    dx = (float)(x1-x0)/dm;
    dy = (float)(y1-y0)/dm;
    x = (float)x0+0.5;//四舍五入
    y = (float)y0+0.5;

    for ( i = 0; i < dm; i++)
    {
        if(!(i%dot)|| i)
        {
            lcd_draw_point(x,y,color);
        }
        x += dx;
        y += dy;
    }
}



/*全屏颜色刷新*/
void gui_color_fill(uint16_t color)
{
	uint8_t data[2] = {(color >> 8),color & 0xFF};
    for (uint16_t i = 0; i < LCD_HIGH; i++)
    {
        for (uint16_t j = 0; j < LCD_WIDTH; j++)
        {
            LCD_GRAM [i][j][0] = data[0];
            LCD_GRAM [i][j][1] = data[1];
        }
    }
}

// 画实心矩形的函数  
void lcd_draw_solid_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {  
    // 检查输入参数是否有效（例如，确保 x1 <= x2 和 y1 <= y2）  
    if (x1 > x2 || y1 > y2) {  
        return;  
    }  
    for (uint16_t x = x1; x <= x2; x++) {  
        for (uint16_t y = y1; y <= y2; y++) {  
            lcd_draw_point(x, y, color);  
        }  
    }  
}

/*显示一个数字*/
void gui_show_num16_one(uint8_t x,uint16_t y,uint16_t num,uint16_t fore_color,uint16_t back_color)
{
	uint8_t m,temp,i;	
	for (i = 0; i < 16; i++)
	{
		temp = ascii_1608[16+num][i];
		for (m = 0; m < 8; m++) //逐行式 一个八位递增
		{
			if (temp&0x01)
			{
                lcd_draw_point(x+m,y+i,fore_color);
			}
			else
			{
                lcd_draw_point(x+m,y+i,back_color);
			}
			temp >>= 1;
		}
	}
}

void gui_show_num16_2(uint8_t x,uint16_t y,uint16_t num,uint16_t fore_color,uint16_t back_color)
{
	gui_show_num16_one(x,y,(num/10)%10,fore_color,back_color);
	gui_show_num16_one(x+8,y,num%10,fore_color,back_color);
}

void gui_show_volume_num(uint8_t x,uint16_t y,uint16_t num,uint16_t fore_color,uint16_t back_color,uint8_t vol_step_120_on)
{
    if (vol_step_120_on == 1) // 120级
    {
        uint8_t x_Third = num / 100;
        uint8_t x_Dec = (num < 100) ? (num / 10) : ((num / 10) - 10);
        uint8_t x_Bit = num % 10;
        gui_show_num16_one(x, y, x_Third,fore_color,back_color);
        gui_show_num16_one(x + 8, y, x_Dec,fore_color,back_color);
        gui_show_num16_one(x + 16, y, x_Bit,fore_color,back_color);
    }else{
        // 60级
        uint8_t x_Dec = num / 10;
        uint8_t x_Bit = num % 10;
        gui_show_num16_one(x, y, x_Dec,fore_color,back_color);
        gui_show_num16_one(x + 8, y, x_Bit,fore_color,back_color);
    }
}

/*
显示数字，智能识别长度
*/
void gui_show_num_uint(uint8_t x,uint16_t y,uint32_t num,uint16_t fore_color,uint16_t back_color)
{
    uint32_t temp = num;  
    uint8_t int_digits = 0;
    // 计算整数部分的位数  
    while (temp > 0) {  
        temp /= 10;  
        int_digits++;  
    }

	// 如果整数部分为0，则至少显示一个'0'  
    if (int_digits == 0) {  
        gui_show_num16_one(x, y,0, fore_color, back_color);  
        int_digits = 1; // 更新位数以便显示小数点  
    } 

    // 显示整数部分，从最高位开始  
    temp = num;  
    for (int i = int_digits - 1; i >= 0; i--) {  
        uint8_t digit = temp % 10; // 直接取余数得到当前位的数字  
        gui_show_num16_one(x + 8 * i, y, digit, fore_color, back_color); // 转换为字符并显示  
        temp /= 10; // 为下一次迭代准备  
    }
}


//针对8x16的显示函数 lcd会递增 取模软件设置逐行式
void gui_show_char16(uint16_t  x,uint16_t y,uint8_t font,uint16_t fore_color,uint16_t back_color)
{
	uint8_t font_num = font-32;//ascll码从32 空格开始
	uint8_t m,temp,i;
	uint16_t arr_length = 16;//字体高度  16x16 一共需要32个8位   16*16/8
	for (i = 0; i < arr_length; i++)
	{
		temp = ascii_1608[font_num][i];
		for (m = 0; m < 8; m++) //逐行式 一个八位递增
		{
			if (temp&0x01)
			{
                lcd_draw_point(x+m,y+i,fore_color);
			}
			else
			{
                lcd_draw_point(x+m,y+i,back_color);
			}
			temp >>= 1;
		}
	}
}

void gui_show_string16(uint16_t  x,uint16_t y, const uint8_t *font,uint8_t font_num,uint16_t fore_color,uint16_t back_color)
{
	for (uint8_t i = 0; i < font_num; i++)
	{
		gui_show_char16(x+8*i,y,font[i],fore_color,back_color);
	}
}


//针对8x16的显示函数 lcd会递增 取模软件设置逐行式
void gui_show_char16x24(uint16_t  x,uint16_t y,uint8_t font,uint16_t fore_color,uint16_t back_color)
{
    uint8_t font_num = font-32;//ascll码从32 空格开始
	uint8_t m,temp,i,j;
	uint16_t arr_high = 24;
    uint8_t arr_wide = 16;
    uint8_t arr_wide_byte = arr_wide/8;
	for (i = 0; i < arr_high; i++)
	{
        for (j = 0; j < arr_wide_byte; j++)
        {
            temp = ascii_sampling[font_num][i*arr_wide_byte+j];
            for (m = 0; m < 8; m++) //逐行式 一个八位递增
            {
                if (temp&0x01)
                {
                    lcd_draw_point(x+m+j*8,y+i,fore_color);
                }
                else
                {
                    lcd_draw_point(x+m+j*8,y+i,back_color);
                }
                temp >>= 1;
            }
        }
	}
}

void gui_show_string16x24(uint16_t  x,uint16_t y, uint8_t *font,uint8_t font_num,uint16_t fore_color,uint16_t back_color)
{
	for (uint8_t i = 0; i < font_num; i++)
	{
		gui_show_char16x24(x+16*i,y,font[i],fore_color,back_color);
	}
}

void gui_show_char16x22(uint16_t  x,uint16_t y,uint8_t font,uint16_t fore_color,uint16_t back_color)
{
    uint8_t font_num = font-32;//ascll码从32 空格开始
	uint8_t m,temp,i,j;
	uint16_t arr_high = 22;
    uint8_t arr_wide = 16;
    uint8_t arr_wide_byte = arr_wide/8;
	for (i = 0; i < arr_high; i++)
	{
        for (j = 0; j < arr_wide_byte; j++)
        {
            temp = ascii_eq[font_num][i*arr_wide_byte+j];
            for (m = 0; m < 8; m++) //逐行式 一个八位递增
            {
                if (temp&0x01)
                {
                    lcd_draw_point(x+m+j*8,y+i,fore_color);
                }
                else
                {
                    lcd_draw_point(x+m+j*8,y+i,back_color);
                }
                temp >>= 1;
            }
        }
	}
}

void gui_show_string16x22(uint16_t  x,uint16_t y, uint8_t *font,uint8_t font_num,uint16_t fore_color,uint16_t back_color)
{
	for (uint8_t i = 0; i < font_num; i++)
	{
		gui_show_char16x22(x+16*i,y,font[i],fore_color,back_color);
	}
}

/*任意位置刷新图片
x，y:刷新起始点
图片的长宽
应该增加一个图片的解析
*/
void gui_show_pic(uint16_t x,uint16_t y,uint16_t pic_w,uint16_t pic_h,uint8_t *p)
{
    uint16_t color;
    uint16_t cursor_x;
    for (uint16_t j = 0; j < pic_h; j++)
    {
        for (uint16_t i = 0; i < pic_w; i++)
        {
            cursor_x = i*2+pic_w*j*2;
            color = (p[cursor_x]<<8) + (p[cursor_x+1]);
            lcd_draw_point(x+i,y+j,color);     
        }
    }
}

/*
解析图片，将图片任意位置矩形，拷贝要缓存数组上。(高效率，直接拷贝)
x,y:显示起始位置坐标
pic_w,pic_h:解析图片的宽高
pic_src_x,pic_src_y ：解析图片矩形的坐标
pic_src_w，pic_src_h:解析图片矩形的宽高
*/
void gui_show_pic_any(uint16_t x, uint16_t y,   
                  uint16_t pic_w, uint16_t pic_h,   
                  uint16_t pic_src_x, uint16_t pic_src_y,   
                  uint16_t pic_src_w, uint16_t pic_src_h,   
                const  uint8_t *p)  
{  
    uint16_t dest_y;  
    uint8_t * temp = NULL;
    if (pic_src_x + pic_src_w > pic_w || pic_src_y + pic_src_h > pic_h) {
        return;  
    } 
    if (x+pic_src_w>LCD_WIDTH||y+pic_src_h>LCD_HIGH)
    {
        return;
    }
    for (dest_y = 0; dest_y < pic_src_h; dest_y++) {
        temp = (uint8_t *)p+pic_src_x*2 +(pic_w*2*pic_src_y)+(pic_w*2*dest_y);
        memcpy(&LCD_GRAM[y+dest_y][x][0],temp,(pic_src_w*2));
    }  
}

//图片旋转函数，打点法，
/*
顺时针
x1=xcos(β)-ysin(β);
y1=ycos(β)+xsin(β);

x1=xcos(β)+ysin(β);
y1=ycos(β)-xsin(β);

//0绕原点计算公式
// xpose=0+cos_value*(x+i)-sin_value*(y+j);
// ypose=0+cos_value*(y+j)+sin_value*(x+i);

// xpose = (x+i) - cos_value * ((x+i) - x0) + sin_value * ((y+j) - y0);
// ypose = (y+j) - sin_value * ((x+i) - x0) - cos_value * ((y+j) - y0);

//绕某个坐标放大缩小
// xpose = (x+i) - cos_value * ((x+i) - center_x) + sin_value * ((y+j) - center_y);
// ypose = (y+j) - sin_value * ((x+i) - center_x) - cos_value * ((y+j) - center_y);

//缺少线性插值
//做一个图片坐标数据的变换,用屏幕坐标法实现的缓存刷新
*/
void gui_show_pic_turn(uint16_t x,uint16_t y,uint16_t pic_w,uint16_t pic_h,
uint16_t rotate,uint16_t center_x,uint16_t center_y, uint8_t *p)
{
    uint16_t color;
    uint16_t cursor_x;

    int32_t xpose, ypose;
    int32_t sin_value = SIN[rotate]*256;
    int32_t cos_value = COS[rotate]*256; 
    int diff_x;
    int diff_y;

    for (uint16_t j = 0; j < pic_h; j++)
    {
        for (uint16_t i = 0; i < pic_w; i++)
        {
            cursor_x = i*2+pic_w*j*2;
            color = (p[cursor_x]<<8) + (p[cursor_x+1]);

            diff_x = (x+i) - center_x;
            diff_y = (y+j) - center_y;

            xpose = center_x + ((cos_value * diff_x + sin_value * diff_y)>>8);
            ypose = center_y + ((sin_value * diff_x - cos_value * diff_y)>>8);   

            if (x>LCD_WIDTH|| y>LCD_HIGH)
            {
                continue;
            }
            lcd_draw_point(xpose,ypose,color);  
            lcd_draw_point(xpose-1,ypose,color); 
        }
    }
}


void Drawarc(int x,int y,int a,int b,uint16_t r,uint16_t c)
{
    float rad,x_tp,y_tp,i;
    i=a;
    for(;i<b;i=i+0.2)//此处写0.2是为了提高精度 不然半径过大有时会有虚线
    {    
        rad=0.01745*i;
        x_tp=r*cos(rad)+x;
        y_tp=-r*sin(rad)+y;        
        lcd_draw_point((uint16_t)x_tp,(uint16_t)y_tp,c);    
    }
}

//在xy矩形内 画半径r的圆角矩形 画笔颜色为c
void DrawArcRect(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t r,uint32_t c)
{
	//先画4个没有圆角的矩形
	Gui_DrawLine_Bresenham(x1+r,y1,x2-r,y1,c);
	Gui_DrawLine_Bresenham(x1,y1+r,x1,y2-r,c);
	Gui_DrawLine_Bresenham(x1+r,y2,x2-r,y2,c);
	Gui_DrawLine_Bresenham(x2,y1+r,x2,y2-r,c);
	//再画四个圆角
	Drawarc(x1+r,y1+r,90,180,r,c);	
	Drawarc(x2-r,y1+r,0,90,r,c);
	Drawarc(x1+r,y2-r,180,270,r,c);
	Drawarc(x2-r,y2-r,270,360,r,c);
}





#define LCD_DATA_BUFFER_MAX_LEN 512
#define LCD_IMAGE_DATA_HEADER_LEN 6

/*灰度图片要带头文件
16灰图片显示
example
uint16_t color_list[16];
ld_hd_text_color_list_calc(color_list, 16, 0xf800,0);
ld_send_hd_text_data(0,0,160,80,gImage_k2,6406,color_list,16);
*/
void ld_send_hd_text_data(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *data, uint16_t data_length, uint16_t* color_list, uint16_t color_list_len) {  
    if(!data || data[1] != 4 || color_list_len < 16)//图片头文件判定
    {
        return;
    }
    // 注意文本取模时要使用白色作为前景色，黑色作为背景色，颜色范围为16灰  
    if (data_length == 0) {  
        data_length = ((width + 1) / 2) * height; // 注意这里已经是按字节计算了  
    }  
    uint16_t color_temp;  
    // 遍历数据并存储到LCD_GRAM中  
    for (uint16_t row = 0; row < height; row++) {  
        for (uint16_t col = 0; col < width; col++) {  
            // 计算当前像素对应的字节索引和位偏移  
            uint16_t byte_idx = (row * width + col) / 2;  
            uint8_t bit_idx = (row * width + col) % 2 * 4; // 0或4，表示像素在字节中的位置（高位或低位）  
  
            // 提取灰度值，注意这里使用了位运算来提取4位的灰度值  
            uint8_t gray_value = (data[byte_idx + LCD_IMAGE_DATA_HEADER_LEN] >> (4 - bit_idx)) & 0x0F;
            // 使用颜色列表将灰度值映射到RGB565颜色值  
            color_temp = color_list[gray_value];  
            // 存储到LCD_GRAM中，假设LCD_GRAM是一个三维数组，其中第三维用于存储RGB565的高位和低位  
            LCD_GRAM[y + row][x + col][0] = color_temp >> 8; // 高位  
            LCD_GRAM[y + row][x + col][1] = color_temp & 0xFF; // 低位  
        }  
    }  
}  

//图片头文件判定
/*
图片数组需要带头文件
*/
void ld_send_hd_text_data_ez(uint16_t x, uint16_t y,const uint8_t *data, uint16_t data_length, uint16_t* color_list) {  
    uint16_t width = data[3];uint16_t height = data[5];//获取数组头文件信息，长度和宽度
    // 注意文本取模时要使用白色作为前景色，黑色作为背景色，颜色范围为16灰  
    if (data_length == 0) {  
        data_length = ((width + 1) / 2) * height; // 注意这里已经是按字节计算了  
    }  
    uint16_t color_temp;  
    // 遍历数据并存储到LCD_GRAM中  
    for (uint16_t row = 0; row < height; row++) {  
        for (uint16_t col = 0; col < width; col++) {  
            // 计算当前像素对应的字节索引和位偏移  
            uint16_t byte_idx = (row * width + col) / 2;  
            uint8_t bit_idx = (row * width + col) % 2 * 4; // 0或4，表示像素在字节中的位置（高位或低位）  
  
            // 提取灰度值，注意这里使用了位运算来提取4位的灰度值  
            uint8_t gray_value = (data[byte_idx + LCD_IMAGE_DATA_HEADER_LEN] >> (4 - bit_idx)) & 0x0F;
            // 使用颜色列表将灰度值映射到RGB565颜色值  
            color_temp = color_list[gray_value];  
            // 存储到LCD_GRAM中，假设LCD_GRAM是一个三维数组，其中第三维用于存储RGB565的高位和低位  
            LCD_GRAM[y + row][x + col][0] = color_temp >> 8; // 高位  
            LCD_GRAM[y + row][x + col][1] = color_temp & 0xFF; // 低位  
        }  
    }  
}


void ld_hd_text_color_list_calc(uint16_t* color_list, uint16_t color_list_len, uint16_t text_color, uint16_t background_color)
{
    if(!color_list || color_list_len < 16)
        return;

    rgb_color_t background_color_rgb = {RGB_RED_OF_COLOR16(background_color), RGB_GREEN_OF_COLOR16(background_color), RGB_BLUE_OF_COLOR16(background_color)};
    rgb_color_t text_color_rgb = {RGB_RED_OF_COLOR16(text_color), RGB_GREEN_OF_COLOR16(text_color), RGB_BLUE_OF_COLOR16(text_color)};

    //取模的源数据是黑白的，所以有14级渐变
    int8_t r_step = ((int16_t)text_color_rgb.r - background_color_rgb.r) / 14;
    int8_t g_step = ((int16_t)text_color_rgb.g - background_color_rgb.g) / 14;
    int8_t b_step = ((int16_t)text_color_rgb.b - background_color_rgb.b) / 14;

    color_list[0] = text_color;

    uint8_t r, g, b;
    for(uint8_t i = 1; i <= 14; i++)
    {
        r = text_color_rgb.r - (i * r_step);
        g = text_color_rgb.g - (i * g_step);
        b = text_color_rgb.b - (i * b_step);

        color_list[i] = RGB_TO_COLOR16(r, g, b);
    }
    color_list[15] = background_color;
}



